﻿#include "pch.h"

namespace fs = std::filesystem;

// 采用测试前置条件：GC设置采用方法时长0.2分钟。
class SamplingTest : public ::testing::Test
{
protected:
    void SetUp() override
    {
        std::cout << "SetUp" << std::endl;
        // 创建测试用的OrgFile句柄
        testHandle = createOrgFile("sampling_test");
        pChannelSampling = getChannelSamplingPtr();
        ASSERT_GT(testHandle, 0);

        // 预设谱图信息
        TOrgHead orgHead;
        EXPECT_TRUE(getOrgHead(testHandle, &orgHead));
        orgHead.Sample[0].Minutes = orgHead.Sample[1].Minutes = 20; // 采样时长0.2分钟，12秒
        orgHead.Detector = 0x0001ffff;
        orgHead.Frequency = 20;
        EXPECT_TRUE(setOrgHead(testHandle, &orgHead));

        // 初始化采样配置
        initBridgeAnalysis("config.ini");

        tagMotherBoardInfo motherBoardInfo[2] = {{0, "GC1949", "1.0"}, {1, "GC1949", "1.0"}};
        tagTIPPortInfo redisAddr = {0, "127.0.0.1", 6379};
        EXPECT_EQ(ChemDevLayerInit((LPBYTE)&motherBoardInfo[0], (LPBYTE)&redisAddr), 0);

        tagTIPPortInfo IPPortInfo = {1, "192.168.114.156", 9100};
        EXPECT_EQ(ChemDevLayerConnect(0, (LPBYTE)&IPPortInfo), 0);
        std::this_thread::sleep_for(3s);
        EXPECT_EQ(ChemDevLayerInitGC(0), 0);
        std::this_thread::sleep_for(3s);
    }

    void TearDown() override
    {
        std::cout << "TearDown" << std::endl;
        if (testHandle > 0)
        {
            closeOrgFile(testHandle);
        }
        EXPECT_EQ(ChemDevLayerDisConnect(0), 0);

        fs::remove("saved.method");
    }

    int64_t testHandle = -1;
    TChannelSampling *pChannelSampling = nullptr;
};

// 测试用例1.1、1.2、1.3测试前方法采样时长设置为0.2分钟(12秒)
// 测试用例1.1：正常开始和停止采样流程(12s卡点停止采样)
TEST_F(SamplingTest, NormalStartStopSequence_1_1)
{
    // 异常采样流程：不调用设备层ChemDevLayerInstGCStart，直接调用startSample
    // 预期超时未响应做样数据
    EXPECT_FALSE(startSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_START_TIMEOUT);

    // 正常采样流程：先调用设备层ChemDevLayerInstGCStart，再调用startSample
    // 响应第一批做样数据后，startSample正常返回
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    // 验证采样状态
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_TRUE(pChannelSampling != nullptr);
    EXPECT_TRUE(pChannelSampling->isSampling());
    EXPECT_EQ(pChannelSampling->getOrgHandle(), testHandle);

    std::this_thread::sleep_for(12s);

    // 停止采样
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_TRUE(stopSample(testHandle));

    // 验证采样已停止
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_FALSE(pChannelSampling);
}

// 测试用例1.2：正常开始和停止采样流程(5s提前停止采样)
TEST_F(SamplingTest, NormalStartStopSequence_1_2)
{
    // 异常采样流程：不调用设备层ChemDevLayerInstGCStart，直接调用startSample
    // 预期超时未响应做样数据
    EXPECT_FALSE(startSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_START_TIMEOUT);

    // 正常采样流程：先调用设备层ChemDevLayerInstGCStart，再调用startSample
    // 响应第一批做样数据后，startSample正常返回
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    // 验证采样状态
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_TRUE(pChannelSampling != nullptr);
    EXPECT_TRUE(pChannelSampling->isSampling());
    EXPECT_EQ(pChannelSampling->getOrgHandle(), testHandle);

    std::this_thread::sleep_for(5s);

    // 停止采样
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_TRUE(stopSample(testHandle));

    // 验证采样已停止
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_FALSE(pChannelSampling);
}

// 测试用例1.3：正常开始和停止采样流程(20s延后停止采样)
TEST_F(SamplingTest, NormalStartStopSequence_1_3)
{
    // 异常采样流程：不调用设备层ChemDevLayerInstGCStart，直接调用startSample
    // 预期超时未响应做样数据
    EXPECT_FALSE(startSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_START_TIMEOUT);

    // 正常采样流程：先调用设备层ChemDevLayerInstGCStart，再调用startSample
    // 响应第一批做样数据后，startSample正常返回
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    // 验证采样状态
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_TRUE(pChannelSampling != nullptr);
    EXPECT_TRUE(pChannelSampling->isSampling());
    EXPECT_EQ(pChannelSampling->getOrgHandle(), testHandle);

    std::this_thread::sleep_for(20s);

    // 停止采样
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_FALSE(stopSample(testHandle));

    // 验证采样已停止
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_FALSE(pChannelSampling);
}

// 测试用例2：重复开始采样
TEST_F(SamplingTest, DuplicateStartSampling)
{
    // 第一次开始采样应该成功
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    // 第二次开始采样应该失败
    EXPECT_FALSE(startSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_ORG_HANDLE_IS_SAMPLING);

    // 清理
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    stopSample(testHandle);
}

// 测试用例3：无效句柄开始采样
TEST_F(SamplingTest, StartWithInvalidHandle)
{
    // 无效句柄
    const int64_t invalidHandle = 999;

    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_FALSE(startSample(invalidHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_ORG_HANDLE_NOT_EXIST);
}

// 测试用例4：停止未开始的采样
TEST_F(SamplingTest, StopWithoutStarting)
{
    EXPECT_FALSE(stopSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_CHANNEL_IS_NOT_SAMPLING);
}

// 测试用例5：停止错误的句柄采样
TEST_F(SamplingTest, StopWithWrongHandle)
{
    // 开始采样
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    // 使用错误的句柄停止
    const int64_t wrongHandle = createOrgFile("sampling_test_wrong_handle");
    EXPECT_FALSE(stopSample(wrongHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_ORG_HANDLE_IS_NOT_SAMPLING);

    // 正确停止
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    stopSample(testHandle);
}

// 测试用例6：采样超时处理
TEST_F(SamplingTest, SamplingTimeoutHandling)
{
    // 使用自定义配置缩短超时时间以便测试
    EXPECT_EQ(ChemDevLayerDisConnect(0), 0);
    TChannelSampling::SamplingConfig config;
    config.redis_timeout_msec = 2000;     // Redis超时N1毫秒未收到数据异常
    config.start_timeout_msec = 5000;     // 启动采样N2毫秒内数据未切变采样状态
    config.stop_timeout_msec = 5000;      // 停止采样N3毫秒内数据未切变基线状态
    config.stop_time_sync_msec = 5000;    // 停止时间与当前时间不同步，差异超N4毫秒
    config.gatcher_time_sync_msec = 5000; // 采样时长与方法时长不同步，差异超N5毫秒

    pChannelSampling = new TChannelSampling(config);
    pChannelSampling->setOrgHandle(testHandle);

    // 开始采样
    pChannelSampling->StartSampling();

    // 等待超时发生
    std::this_thread::sleep_for(std::chrono::milliseconds(1500));

    // 验证超时错误
    EXPECT_TRUE(pChannelSampling->hasError());
    EXPECT_EQ(pChannelSampling->getLastErrorCode(), ERR_CODE_REDIS_TIMEOUT);

    // 停止采样
    EXPECT_FALSE(pChannelSampling->StopSampling());
    delete pChannelSampling;
}

// 测试用例7：采样数据保存验证
TEST_F(SamplingTest, SamplingDataSaving)
{
    TChannelSampling::SamplingConfig config;
    std::unique_ptr<TChannelSampling> ptr = std::make_unique<TChannelSampling>(config);
    pChannelSampling = ptr.get();
    pChannelSampling->setOrgHandle(testHandle);

    TOrgHead orgHead;

    EXPECT_TRUE(getOrgHead(testHandle, &orgHead));
    orgHead.Detector = 0x1001ffff; // 通道1对应设备1/检测器0，通道2对应设备0/检测器1
    setOrgHead(testHandle, &orgHead);

    // 模拟接收数据
    std::vector<TRawItem> testData1 = {
        {1, 1000, 100}, // Status=1表示采样数据
        {1, 2000, 200},
        {0, 3000, 50} // Status=0表示基线数据
    };

    std::vector<TRawItem> testData2 = {
        {1, 1000, 100}, // Status=1表示采样数据
        {1, 2000, 200},
        {1, 3000, 50} // Status=0表示基线数据
    };

    // 处理数据
    pChannelSampling->ProcessSpectrumData(1, 0, testData1);
    pChannelSampling->ProcessSpectrumData(0, 1, testData2);

    pChannelSampling->saveDataToOrgFile();

    // 验证数据是否保存到OrgFile
    EXPECT_TRUE(getOrgHead(testHandle, &orgHead));
    EXPECT_EQ(orgHead.RawDataCount[0], 2);
    EXPECT_EQ(orgHead.RawDataCount[1], 3);
}

// 测试用例8：并发测试，已删

// 测试用例9：采样状态检查
TEST_F(SamplingTest, SamplingStatusCheck)
{
    // 初始状态检查
    EXPECT_FALSE(pChannelSampling);

    // 开始采样
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_TRUE(pChannelSampling->isSampling());
    EXPECT_TRUE(pChannelSampling->isOrgHandleSampling(testHandle));

    std::this_thread::sleep_for(12s);

    // 停止采样
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_TRUE(stopSample(testHandle));
    pChannelSampling = getChannelSamplingPtr();
    EXPECT_FALSE(pChannelSampling);
}

// 测试用例10：采样时间同步验证
TEST_F(SamplingTest, SamplingTimeSyncValidation)
{
    // 设置采样时长
    TOrgHead orgHead;
    EXPECT_TRUE(getOrgHead(testHandle, &orgHead));
    orgHead.Sample[0].Minutes = 100; // 1分钟
    EXPECT_TRUE(setOrgHead(testHandle, &orgHead));

    // 使用自定义配置缩短同步时间以便测试
    TChannelSampling::SamplingConfig config;
    config.gatcher_time_sync_msec = 1000; // 1秒同步误差

    std::unique_ptr<TChannelSampling> ptr = std::make_unique<TChannelSampling>(config);
    pChannelSampling = ptr.get();
    pChannelSampling->setOrgHandle(testHandle);

    // 开始采样
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    pChannelSampling->StartSampling();

    // 模拟接收数据
    std::vector<TRawItem> testData;
    for (int32_t i = 0; i < 120; ++i)
    { // 模拟2秒数据
        testData.push_back({1, i * 1000 / 60, 100 + i});
    }
    pChannelSampling->ProcessSpectrumData(0, 0, testData);
    pChannelSampling->ProcessSpectrumData(0, 1, testData);

    // 停止采样
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    pChannelSampling->StopSampling();

    // 验证时间同步，允许采样时长少于设定时长，保存数据验证数据时长与实际时长偏差。
    EXPECT_TRUE(pChannelSampling->hasError());
    EXPECT_EQ(pChannelSampling->getLastErrorCode(), ERR_CODE_GATHER_TIME_NOT_SYNC);
}

// 测试用例11：采样过程中错误处理
TEST_F(SamplingTest, ErrorHandlingDuringSampling)
{ 
    // 开始采样
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));
    pChannelSampling = getChannelSamplingPtr();
    // 模拟错误
    pChannelSampling->setError(ERR_CODE_REDIS_TIMEOUT, "Test error");

    // 停止采样应该反映这个错误
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_FALSE(stopSample(testHandle));
    EXPECT_EQ(getLastErrorCode(), ERR_CODE_REDIS_TIMEOUT);
}

// 测试用例12：采样数据管理器功能
TEST_F(SamplingTest, SpectrumDataManagerFunctionality)
{
    SpectrumDataManager manager;
    TRawItem testPoint = {1, 1000, 100};

    // 添加数据
    manager.addData(0, testPoint);

    // 获取数据
    auto data = manager.getData(0);
    ASSERT_EQ(data.size(), 1);
    EXPECT_EQ(data[0].Time, testPoint.Time);
    EXPECT_EQ(data[0].Data, testPoint.Data);

    // 清理数据
    manager.clear();
    EXPECT_TRUE(manager.getData(0).empty());
}

// 测试用例13：采样线程安全测试
TEST_F(SamplingTest, ThreadSafetyTest)
{
    const int32_t numThreads = 4;
    std::vector<std::thread> threads;
    std::atomic<int32_t> successCount{0};

    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    std::this_thread::sleep_for(3000ms);
    bool stopped = false;
    auto testFunc = [&](int64_t handle)
    {
        if (startSample(handle))
        {
            successCount++;
            std::this_thread::sleep_for(std::chrono::milliseconds(3000));
            if (!stopped)
            {
                EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
                stopped = true;
            }
            stopSample(handle);
        }
        else
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(3000));
            if (!stopped)
            {
                EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
                stopped = true;
            }
        }
    };

    // 创建多个线程尝试开始采样
    for (int32_t i = 0; i < numThreads; ++i)
    {
        threads.emplace_back(testFunc, testHandle);
    }

    for (auto &t : threads)
    {
        if (t.joinable())
        {
            t.join();
        }
    }
    if (!stopped)
    {
        EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
        stopped = true;
    }
    // 应该只有一个线程成功
    EXPECT_EQ(successCount, 1);
}

// 测试用例14：采样数据完整性验证
TEST_F(SamplingTest, SamplingDataIntegrity)
{
    // 开始采样
    EXPECT_EQ(ChemDevLayerInstGCStart(0, false, 0, 0), 0);
    EXPECT_TRUE(startSample(testHandle));

    TOrgHead orgHead;
    EXPECT_TRUE(getOrgHead(testHandle, &orgHead));
    orgHead.Sample[0].Minutes = orgHead.Sample[1].Minutes = 100;
    EXPECT_TRUE(setOrgHead(testHandle, &orgHead));

    // 模拟接收大量数据
    std::vector<TRawItem> testData;
    const int32_t dataSize = 1200;
    for (int32_t i = 0; i < dataSize; ++i)
    {
        testData.push_back({1, i * 10, i % 100});
    }
    pChannelSampling = getChannelSamplingPtr();
    // 处理数据
    pChannelSampling->ProcessSpectrumData4Test(0, 0, testData);
    pChannelSampling->ProcessSpectrumData4Test(0, 1, testData);

    // 停止采样
    TChannelSampling::SamplingState *pState = pChannelSampling->getSamplingState4Test();
    pState->stop_time[0] = now_ms();
    pState->start_time[0] = now_ms() - 60000;
    pState->stop_time[1] = now_ms();
    pState->start_time[1] = now_ms() - 60000;
    EXPECT_EQ(ChemDevLayerInstGCStop(0), 0);
    EXPECT_TRUE(stopSample(testHandle));

    // 验证数据完整性
    getOrgHead(testHandle, &orgHead);
    EXPECT_EQ(orgHead.RawDataCount[0], dataSize);
    int32_t dataRealSize;
    // 需适当放宽，真实采集数据有可能比dataSize大那么一些。
    std::unique_ptr<TRawItem[]> ptr = std::make_unique<TRawItem[]>(dataSize + 20);
    TRawItem *pRaw = ptr.get();
    EXPECT_TRUE(getOrgRawData(testHandle, 0, pRaw, dataSize + 20, &dataRealSize));
    EXPECT_LE(dataSize, dataRealSize);
    EXPECT_GE(dataSize + 20, dataRealSize);
    for (int32_t i = 0; i < dataSize; ++i)
    {
        EXPECT_EQ(pRaw[i].Data, testData[i].Data);
    }
} 

// 测试用例15：采样配置验证
TEST_F(SamplingTest, SamplingConfigValidation)
{
    TChannelSampling::SamplingConfig config;
    // 测试有效配置
    config.start_timeout_msec = 1000;
    EXPECT_NO_THROW({ pChannelSampling = new TChannelSampling(config); delete pChannelSampling; });

    // 测试无效配置
    config.start_timeout_msec = -1;
    // DEATH 测试会导致后续GC连接初始化失败，暂时屏蔽。应该放置在最后测试DEATH
    // EXPECT_DEATH({ pChannelSampling = new TChannelSampling(config); delete pChannelSampling; }, "Assertion failed");
}

#ifdef TEST_SAMPLING
int32_t main(int32_t argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
#endif